home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / mpfeel.lha / MPFeel / Plurals / Modules / ppl.em < prev    next >
Lisp/Scheme  |  1992-07-02  |  26KB  |  873 lines

  1.  
  2. ;
  3. ;       Proper Paralation Lisp
  4. ;
  5. ;       File            : ppl
  6. ;
  7. ;       Contents        : export list:    elwise
  8. ;                    match
  9. ;                    move
  10. ;                    depfun
  11. ;                    choose
  12. ;                    enum
  13. ;                    count
  14. ;                    position
  15. ;                    get
  16. ;                    field-ref (+ setter)
  17. ;                    field-length
  18. ;                    make-paralation
  19. ;                    fieldp
  20. ;
  21. ;       Description     : So called proper paralation lisp because it run
  22. ;              on the processor array. This is better than the last 
  23. ;              version (plisp) as the underlying system is able
  24. ;              to allocate processors in rectangles. So perhaps this
  25. ;              should be bpl (better paralation lisp). This code
  26. ;              rewires the given elwise form into a (hefty) piece
  27. ;              of singular code with calls to parallel 
  28. ;              primitives.
  29. ;
  30. ;       Author          : SCM
  31. ;
  32. ;       Change History  :
  33. ;
  34. ;       Date    Name    Comment
  35. ;     02:06:92  SCM     Created - hacked from plisp.emc
  36. ;     17:06:92  SCM    Added attributes slot and modified get
  37.  
  38.  
  39. ; Include Files
  40. ; ======= =====
  41.  
  42. ; This file has to be run through a preprocessor (empp, uses cpp and sed)
  43. ; to create  a EuLisp readable file. This is because it needs access to
  44. ; constants used by the data parallel lisp primitives written in mpl. The
  45. ; constants distinguish the various lisp types and the types of binary,
  46. ; unary and relational operators available.
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163. (defmodule ppl (standard0 plural ppl-ll) ()
  164.  
  165.  
  166. ; System Configuration
  167. ; ====== =============
  168.  
  169. ; These constants are system defined, the first three indicate the number of
  170. ; physical processors available, GC-TOP varies with the size of heap.
  171.  
  172.   (setq MP-Config 512)
  173.   (setq MP-X-Config 16)
  174.   (setq MP-Y-Config 32)
  175.   (setq GC-TOP (mp-sb-ref))
  176.  
  177.  
  178. ; Debug
  179. ; =====
  180.  
  181. ; xecs are a hangover from eubang (the plurals module) and the connection
  182. ; machine lisp module which was experimentally developed before plisp,
  183. ; it is included here purely for debug purposes as it is the most
  184. ; primitive way of looking at parallel objects, which can be useful
  185. ; when something has gone wrong.
  186.  
  187.   (defclass xec ()
  188.     ((context
  189.       initarg context
  190.       reader  context)
  191.      (offset
  192.       initarg offset
  193.       reader  offset))
  194.     constructor (allocate-xec context offset)
  195.     predicate xecp)
  196.  
  197.   (defun make-xec (c o)
  198.     (become-strange (allocate-xec c o)))
  199.   
  200.   (defmethod generic-prin ((p xec) str)
  201.     (format str "#x(")
  202.     (mp-print (context p) (offset p) () () str)
  203.     (format str ")")
  204.     p)
  205.   
  206.   (defmethod generic-write ((p xec) str)
  207.     (format str "#x(")
  208.     (mp-print (context p) (offset p) () () str)
  209.     (format str ")")
  210.     p)
  211.  
  212.  
  213. ; Paralation Structure
  214. ; ========== =========
  215.  
  216. ; The paralation is a handle on the set of processor you are working
  217. ; on, it contains all sorts of useful information, like how many
  218. ; there are, if they have any shape.
  219. ; Fields, the data parallel objects in paralation lisp, all belong to
  220. ; one (and only one) paralation, hence they have pointer to their
  221. ; paralation structure. A special field, called the index field and
  222. ; enumerates the elements of the paralation is associated with the
  223. ; paralation and so we have a pointer to this field in the paralation
  224. ; structure as well.
  225. ;    We now have the extra slot, attributes, which can be used to
  226. ; store useful information about the paralation, for example in the
  227. ; case of a rectangle its dimensions (in contexts!).
  228.  
  229.   (defclass paralation-internal ()
  230.     ((contexts 
  231.       initarg contexts
  232.       reader contexts-internal)
  233.     (index
  234.      initarg index
  235.      accessor index-internal)
  236.     (shape
  237.      initarg shape
  238.      accessor shape-internal)
  239.     (attributes 
  240.      initarg attributes
  241.      accessor attributes)
  242.     (length
  243.      initarg length
  244.      reader length-internal))
  245.     constructor (allocate-paralation contexts length))
  246.  
  247.  
  248. ; Paralation Object Structure
  249. ; ========== ====== =========
  250.  
  251. ; Paralation objects, anything that require a paralation to make any
  252. ; sense, namely a field or a mapping, which describe communication
  253. ; patterns between fields. These all contain a paralation and a list
  254. ; of offsets into the data parallel heaps which is where the actual
  255. ; data is.
  256.  
  257.   (defclass paralation-object ()
  258.     ((paralation
  259.       initarg paralation
  260.       reader paralation)
  261.     (offsets
  262.      initarg offsets
  263.      accessor offsets))
  264.     predicate paralation-object-p)
  265.   
  266.  
  267. ; Field Structure
  268. ; ===== =========
  269.  
  270. ; First we deal with fields. Notice that we wrap the field allocator
  271. ; with a form which marks the structure as being strange, this is so
  272. ; the GCer can spot tyhem and list them so we can tell the MasPar
  273. ; which of it's objects are still around.
  274.  
  275.   (defclass field (paralation-object)
  276.     ()
  277.     constructor (allocate-field paralation offsets)
  278.     predicate fieldp)
  279.  
  280.   (defun make-field (p o)
  281.     (become-strange (allocate-field p o)))
  282.  
  283. ; The paralation contains the data we are interested in, but in
  284. ; general we have the field structures, so here are functions to get
  285. ; the appropriate values from a field structure.
  286.  
  287.   (defun contexts (p-o) (contexts-internal (paralation p-o)))
  288.  
  289.   (defun index (p-o) (index-internal (paralation p-o)))
  290.  
  291.   (defun shape (p-o) (shape-internal (paralation p-o)))
  292.  
  293.   ((setter setter) shape (lambda (f v) 
  294.    ((setter shape-internal) (paralation f) v)))
  295.  
  296.   (defun field-length (p-o) (length-internal (paralation p-o)))
  297.   
  298. ; Notice how these methods use a combination of immediate and indirect
  299. ; accessors, anyway - now we can print them.
  300.  
  301.   (defmethod generic-prin ((f field) str)
  302.     (if (not (attributes (paralation f)))
  303.       (progn
  304.     (format str "#F(")
  305.     (mp-print (car (contexts f)) (car (offsets f)) () () str)
  306.     (if (cdr (contexts f)) (format str "... )") (format str ")")))
  307.       (let ((context-width (min (vector-ref (attributes (paralation f)) 0) MP-X-Config)))
  308.     (format str "\n#F(")
  309.     (mp-print (car (contexts f)) (car (offsets f)) context-width
  310.           (< context-width (vector-ref (attributes (paralation f)) 0)) str)
  311.     (if (< MP-Y-Config (vector-ref (attributes (paralation f)) 1))
  312.       (format str "\n ... )") (format str " )")))))
  313.  
  314.   (defmethod generic-write ((f field) str)
  315.     (if (not (attributes (paralation f)))
  316.       (progn
  317.     (format str "#F(")
  318.     (mp-print (car (contexts f)) (car (offsets f)) () () str)
  319.     (if (cdr (contexts f)) (format str "... )") (format str ")")))
  320.       (let ((context-width (min (vector-ref (attributes (paralation f)) 0) MP-X-Config)))
  321.     (format str "\n#F(")
  322.     (mp-print (car (contexts f)) (car (offsets f)) context-width
  323.           (< context-width (vector-ref (attributes (paralation f)) 0)) str)
  324.     (if (< MP-Y-Config (vector-ref (attributes (paralation f)) 1))
  325.       (format str "\n   ... )") (format str " )")))))
  326.  
  327. ;  (defmethod generic-prin ((f field) str)
  328. ;    (format str "#F(")
  329. ;    (mapcar (lambda (c o) (mp-print c o () () str)) (contexts f) (offsets f))
  330. ;    (format str ")")
  331. ;    f)
  332. ;  
  333. ;  (defmethod generic-write ((f field) str)
  334. ;    (format str "#F(")
  335. ;    (mapcar (lambda (c o) (mp-print c o () () str)) (contexts f) (offsets f))
  336. ;    (format str ")")
  337. ;    f)
  338.   
  339.  
  340. ; Processor Management
  341. ; ========= ==========
  342.  
  343. ; Paralation Lisp abstracts the number of processors, it does this by
  344. ; having a list of contexts on which the paralation is allocated, data
  345. ; parallel operations are run on each of these one after another. 
  346. ; A context will be a collection of global contexts, that is ones that
  347. ; use the entire array and one that uses only part of the array. We
  348. ; reuse the same global context and pre-allocate it.
  349.  
  350.   (setq MP-Context (mp-make-context MP-X-Config MP-Y-Config))
  351.  
  352.  
  353.   (setq MP-Offsets (cons (mp-scan-op MP-Context (mp-set MP-Context 
  354.                             (mp-bang MP-Context 1)
  355.                             0 0)
  356.                          610) ()))
  357.  
  358.   (setq MP-Nil (mp-bang MP-Context ()))
  359.  
  360. ; This will ensure the global context is garbage collected as we have
  361. ; nailed it into the environment in a form that can be spotted by the
  362. ; collector. 
  363.  
  364.   (setq GC-Protect (list (make-xec MP-Context (car MP-Offsets))
  365.              (make-xec MP-Context MP-Nil)))
  366.  
  367. ; As we allocate large paralations we reuse exisiting indexes for the
  368. ; global context compontents, the two variables below are useful for
  369. ; keeping track of these things and manipulating them in parallel
  370.  
  371.   (setq VMP-Config MP-Config)
  372.   (setq PMP-Config (mp-bang MP-Context MP-Config))
  373.  
  374.   (setq GC-Protect (cons (make-xec MP-Context PMP-Config) GC-Protect))
  375.   
  376. ; As more virtual pes are allocated we need to number them, we reuse
  377. ; the enumerations of the global contexts as they are the same for all
  378. ; paralations and are immutable. Each time another gklobal context is
  379. ; needed produce an enumeration for it (m -> m + config -1)
  380.  
  381.   (defun enough-virtual-pes-p 
  382.     ;; determines wether more enumerations of the global context are needed
  383.     (required) (< required (+ VMP-Config MP-Config)))
  384.  
  385.   (defun more-processors (required)
  386.     ;; if needed allocates more enumerations of the global context
  387.     (labels ((find-last (offsets)
  388.            ;; descends list of enumerations to the last cons cell
  389.            ;; extra enumerations are then tagged onto the list
  390.            (if (cdr offsets) (find-last (cdr offsets))
  391.          ((setter cdr) offsets (make-rest (car offsets)))))
  392.              (make-rest (offset)
  393.            ;; creates list of as many other enumeration nodes as required
  394.            ;; and GC protects them
  395.            (if (enough-virtual-pes-p required) ()
  396.          (let ((new-ofst (mp-bin-op MP-Context offset 
  397.                         PMP-Config     610)))
  398.            (setq VMP-Config (+ VMP-Config MP-Config))
  399.            (setq GC-Protect (cons (make-xec MP-Context new-ofst)
  400.                       GC-Protect))
  401.            (cons new-ofst (make-rest new-ofst))))))
  402.       (find-last MP-Offsets)))
  403.   
  404.   (defun make-hacked-context (size)
  405.     (if (= size 1) (mp-make-context 1 1)
  406.       (let* ((width (ceiling (sqrt (/ size 2))))
  407.          (ctxt (mp-make-context width (ceiling (/ (* 1.0 size) width))))
  408.          (ofst (mp-context ctxt))
  409.          (tmp-pspace (mp-ps-ref))
  410.          (dummy (mp-sb-set tmp-pspace))
  411.          (enum (mp-scan-op ctxt (mp-bang ctxt 1)     610)))
  412.     (mp-if ctxt (mp-rel-op ctxt enum (mp-bang ctxt size)     652))
  413.     (mp-else ctxt)
  414.     (mp-assign ctxt ofst (mp-bang ctxt '(() ())))
  415.     (mp-fi ctxt)
  416.     (mp-ps-set tmp-pspace)
  417.     (mp-sb-set GC-TOP)
  418.     ctxt)))
  419.  
  420.   (defun get-contexts (required)
  421.     ;; allocates contexts for a new paralation, creates new global
  422.     ;; contexts if needed and probably one partial context unigue to
  423.     ;; this paralation
  424.     (if (not (enough-virtual-pes-p required)) (more-processors required) ())
  425.     (labels ((list-of-ctxts (allocated)
  426.            ;; generates the appropriate list of contexts
  427.                (if (>= (+ allocated MP-Config) required)
  428.          (list (make-hacked-context (- required allocated)))
  429.          (cons MP-Context (list-of-ctxts (+ allocated MP-Config))))))
  430.       (list-of-ctxts 0)))
  431.  
  432.   (defun number-segment (ctxt ofst start)
  433.     (mp-assign ctxt ofst (mp-bang ctxt 1))
  434.     (mp-set ctxt ofst 0 start)
  435.     (mp-assign ctxt ofst (mp-scan-op ctxt ofst     610)))
  436.  
  437.   (defun get-offsets (contexts)
  438.     ;; allocates enumeration offsets for the new paralation with the
  439.     ;; given contexts, the global context enumerations are pulled from
  440.     ;; teh list of shared enumerations, a sopecial enumeration is
  441.     ;; allocated for the straggly bit at the end. get-contexts will
  442.     ;; have alloacted the extra virtual processors if needed
  443.     (labels ((list-of-ofsts (contexts offsets allocated)
  444.            ;; generate the appropriate list of offsets
  445.            (cond 
  446.         ((null contexts) ())
  447.         ((eq (car contexts) MP-Context)
  448.          (cons (car offsets) 
  449.                (list-of-ofsts (cdr contexts) (cdr offsets)
  450.                       (+ allocated MP-Config))))
  451.         (t (list (number-segment (car contexts)
  452.                      (mp-make-plural (car contexts))
  453.                      allocated))))))
  454.       (list-of-ofsts contexts MP-Offsets 0)))
  455.  
  456.   (defcondition illegal-operation ())
  457.  
  458. ; Creating a paralation means create the index field for a new
  459. ; paralation which is what we do here.
  460.  
  461.   (defun make-paralation (size)
  462.     (if (< size 1) (error "Cannot create empty paralation" illegal-operation)
  463.       (let ((new-field (make-field (allocate-paralation (get-contexts size)
  464.                             size) 'no-offsets)))
  465.     ((setter offsets) new-field (get-offsets (contexts new-field)))
  466.     ((setter index-internal) (paralation new-field) new-field)
  467.     new-field)))
  468.  
  469.  
  470. ; Obvious operations
  471. ; ======= ==========
  472.  
  473.   (defun field-ref (f i)
  474.     (let ((list-index (/ i MP-Config)))
  475.       (mp-ref (list-ref (contexts f) list-index)
  476.           (list-ref (offsets f) list-index) (remainder i MP-Config))))
  477.  
  478.   ((setter setter) field-ref (lambda (f i v)
  479.      (let ((list-index (/ i MP-Config)))
  480.        (mp-set (list-ref (contexts f) list-index)
  481.            (list-ref (offsets f) list-index) (remainder i MP-Config) v)
  482.        f)))
  483.  
  484. ; And field-length is now a slot accessor!
  485.  
  486.  
  487. ; Operation Overview
  488. ; ========= ========
  489.  
  490. ; Because the same piece of parallel code will have to run on several
  491. ; different contexts the code generated references a global called
  492. ; The-Context, mapping the code across the contexts with the first
  493. ; operation being Set-The-Context will neatly allow us to do this
  494.  
  495. ; Primitives
  496. ; ==========
  497.  
  498. ; These are the operations which wrap all the functions in the plural
  499. ; module which is implemenmted in C and mpl, the parallel versions of
  500. ; the functions are generated by macros which can be found in ppl-ll.em
  501.  
  502.   (p-1-fn mp-un-op negate       620)
  503.   (p-1-fn mp-un-op abs     621)
  504.   (p-2-fn mp-eq eq ())
  505.   (p-2-fn mp-cons cons ())
  506.   (p-1-fn mp-car car ())
  507.   (p-1-fn mp-cdr cdr ())
  508.   (p-1-fn mp-make-vector make-vector())
  509.   (p-1-fn mp-vector-length vector-length ())
  510.   (p-2-fn mp-vector-ref vector-ref ())
  511.   (p-1-fn mp-test consp 2)
  512.   (p-1-fn mp-test intp 1)
  513.   (p-1-fn mp-test floatp 4)
  514.   (p-1-fn mp-test vectorp 3)
  515.   (p-2-fn mp-bin-op binary-plus     610)
  516.   (p-2-fn mp-bin-op +     610)
  517.   (p-2-fn mp-bin-op binary-difference 611)
  518.   (p-2-fn mp-bin-op - 611)
  519.   (p-2-fn mp-bin-op binary-times 613)
  520.   (p-2-fn mp-bin-op * 613)
  521.   (p-2-fn mp-bin-op binary-divide 612)
  522.   (p-2-fn mp-bin-op / 612)
  523.   (p-2-fn mp-rel-op binary-gt     651)
  524.   (p-2-fn mp-rel-op >     651)
  525.   (p-2-fn mp-rel-op binary-lt     650)
  526.   (p-2-fn mp-rel-op <     650)
  527.   (p-2-fn mp-bin-op remainder 614)
  528.   (p-0-fn mp-random c-rand ())
  529.   (p-2-fn mp-and and ())
  530.   (p-2-fn mp-or or ())
  531.   (p-1-fn mp-not not ())
  532.   
  533.   (p-2-fn mp-assign setq ())
  534.  
  535.   (p-3-set mp-vector-set vector-ref ())
  536.   (p-2-set mp-rplac-a car ())
  537.   (p-2-set mp-rplac-d cdr ())
  538.  
  539. ; There are a few lisp functions who work in parallel - this is a hack!
  540.  
  541.   ((setter table-ref) pfun-table 'progn (cons 'progn ()))
  542.  
  543.  
  544. ; Elwise
  545. ; ======
  546.  
  547. ; The-Context hackery, global binding and a function to set it so that
  548. ; this can be exported.
  549.  
  550.   (setq The-Context 'none)
  551.  
  552.   (defun Set-The-Context (v) (setq The-Context v))
  553.  
  554. ; The heart of the rewriting operation, pull the appropriate functions
  555. ; out og the pfun-tables, bangs singular values with special hackery
  556. ; for cond, let, lambda and if.
  557.  
  558.   (defun rewire (form)
  559.     (cond 
  560.      ((consp form)
  561.       (cond
  562.        ((eq (car form) 'quote) (list 'mp-bang 'The-Context form))
  563.        ((eq (car form) (car function-name)) (cons (cadr function-name)
  564.                           (rewire (cdr form))))
  565.        ((eq (car form) 'if) (elwise-if (cadr form) (caddr form) (cadddr form)))
  566.        ((eq (car form) 'setter) (car (get-psetter (cadr form))))
  567.        ((eq (car form) 'cond) (cons 'let (cons '((cond-result 
  568.                         (mp-make-plural The-Context)))
  569.                     (cons '(mp-if The-Context (mp-bang The-Context t))
  570.                       (rewire-cond (cdr form))))))
  571.        ((eq (car form) 'lambda) (rewire-lambda (cdr form)))
  572.        ((eq (car form) 'let) (rewire-let (cdr form)))
  573.        (t (cons (if (car form) (rewire (car form)) MP-Nil)
  574.         (rewire (cdr form))))))
  575.      ((numberp form) (list 'mp-bang 'The-Context form))
  576.      ((memq form arg-list) form)
  577.      ((get-pfun form) (car (get-pfun form)))
  578.      ((null form) ())
  579.      (t (list 'mp-bang 'The-Context form))))
  580.  
  581.   (defun rewire-cond (form)
  582.     (if (null form) '((mp-fi The-Context) cond-result)
  583.       (cons
  584.        (list 'if (list 'mp-if 'The-Context (rewire (caar form)))
  585.          (list 'mp-assign 'The-Context 
  586.            'cond-result(rewire (cadar form))) ())
  587.        (cons '(mp-file The-Context)
  588.          (rewire-cond (cdr form))))))
  589.        
  590.   (defun rewire-let (form)
  591.     (let ((old-arg-list arg-list))
  592.       (setq arg-list (append (mapcar car (car form)) arg-list))
  593.       (let ((r-form (list 'let (mapcar (lambda (n-f-p)
  594.                      (cons (car n-f-p) 
  595.                            (rewire (cdr n-f-p))))
  596.                        (car form)) (cons 'progn (mapcar rewire 
  597.                                (cdr form))))))
  598.     (setq arg-list old-arg-list)
  599.     r-form)))
  600.  
  601.   (defun rewire-lambda (form)
  602.     (let ((old-arg-list arg-list))
  603.       (setq arg-list (append (car form) arg-list))
  604.       (let ((r-form (list 'lambda (car form) (rewire (cadr form)))))
  605.     (setq arg-list old-arg-list)
  606.     r-form)))
  607.  
  608.   (defun elwise-if (bool then else)
  609.     (let ((then (if then (rewire then) MP-Nil))
  610.       (else (if else (rewire else) MP-Nil)))
  611.       (list 'let '((if-result (mp-make-plural The-Context)))
  612.         (list 'if (list 'mp-if 'The-Context (rewire bool))
  613.           (list 'mp-assign 'The-Context 'if-result then) ())
  614.         (list 'if (list 'mp-else 'The-Context)
  615.           (list 'mp-assign 'The-Context 'if-result else) ())
  616.         '(mp-fi The-Context)
  617.         'if-result)))
  618.  
  619. ; This function is responsible for creating the code which sets
  620. ; everything up before the parallel code is ionvoked, creates bindings
  621. ; to offsets into the data parallel heap rather than front-end
  622. ; structures, code to evaluate any let forms in the elwise parameter
  623. ; list and extracts the book-keeping info (namely the paralation
  624. ; structure) from one of the parameter fields.
  625. ; It also sets up the arg-list, that is the list of parameter field
  626. ; which are kept in a globally accessible place so we can spot when we
  627. ; don't need to bang something.
  628.  
  629.   (defun eval-arg-list (arg-form)
  630.     (if (null arg-form)
  631.       (list (list 'the-contexts (list 'contexts (car arg-list)))
  632.         (list 'the-paralation (list 'paralation (car arg-list)))
  633.         '(the-offsets (mapcar mp-make-plural the-contexts))
  634.         '(the-result (make-field the-paralation the-offsets)))
  635.       (if (consp (car arg-form))
  636.         (progn 
  637.           (setq arg-list (cons (caar arg-form) arg-list))
  638.           (cons (car arg-form) (eval-arg-list (cdr arg-form))))
  639.         (progn 
  640.           (setq arg-list (cons (car arg-form) arg-list))
  641.           (eval-arg-list (cdr arg-form))))))
  642.  
  643.   (defun extract-offsets (arg-list) 
  644.     ;; gets the offset lists from each of the elwise parameter fields,
  645.     ;; these oo are spliced into the rewritten code. 
  646.     (mapcar (lambda (f) (list `offsets f)) arg-list))
  647.  
  648.   (defmacro elwise (arg-form body)
  649.     ;; And this is the hoopty-hoopty-doo-do macro itself which puts
  650.     ;; all the bits in the write place.
  651.     (setq arg-list ())
  652.     (setq function-name '(none))
  653.     `(let* ,(eval-arg-list arg-form)
  654.        (mapcar (lambda ,(cons `the-context 
  655.                   (cons 'result-ofst arg-list))
  656.          (let ((tmp-pspace (mp-ps-ref)))
  657.            (mp-sb-set tmp-pspace)
  658.            (Set-The-Context the-context)
  659.            (mp-assign The-Context result-ofst
  660.                   ,(if body (rewire body) 
  661.                  (list 'mp-bang 'The-Context ())))
  662.            (mp-sb-set GC-TOP)
  663.            (mp-ps-set tmp-pspace)
  664.            result-ofst))
  665.            ,@(cons `the-contexts (cons `the-offsets 
  666.                        (extract-offsets arg-list))))
  667.        the-result))
  668.        
  669. ; to add primitives, particularly recursive primitives
  670.  
  671.   (defmacro depfun (name args body)
  672.     (setq arg-list args)
  673.     (setq function-name (list name (make-pfun-name name)))
  674.     (add-pfun name (cadr function-name) args)
  675.     `(progn (defun ,(cadr function-name) ,args ,(rewire body))
  676.         (export ,(cadr function-name))))
  677.  
  678.  
  679. ; Mappings
  680. ; ========
  681.  
  682. ; Mappings describe communication bewteen paralations. They are a
  683. ; special kind of plural. Without virtualisation they are easy to
  684. ; understand. Each element of the paralation contains a list of
  685. ; processor numbers which an object should be taken from. In the
  686. ; virtualisation we have to handle the mxn combinations of contexts,
  687. ; hence rather than a list of offsets, we have a list of lists of
  688. ; offsets , which gives us all the informationwe need.
  689.  
  690.   (defclass mapping (paralation-object)
  691.     ()
  692.     constructor (make-mapping paralation offsets)
  693.     predicate mappingp)
  694.   
  695.   (defun allocate-mapping (p o)
  696.     (become-strange (make-mapping p o)))
  697.  
  698.  
  699. ; Communications
  700. ; ==============
  701.  
  702. ; Strictly speaking anything which isn't elwise I guess
  703.  
  704. ; Match
  705. ; =====
  706.  
  707. ; This is indeed a most nasty operation, zipping along lists of
  708. ; contexts and offsets at slightly different rates, not turning down a
  709. ; cdr, suddenly dropping dead of myxamatosis!
  710.  
  711.   (defun match (dest from)
  712.     (let ((result (allocate-mapping 
  713.            (paralation dest) 
  714.            (mapcar (lambda (d-c) (mapcar (lambda (f-c) 
  715.                            (mp-make-plural d-c))
  716.                          (contexts from)))
  717.                (contexts dest))))
  718.            (tmp-pspace (mp-ps-ref)))
  719.       (mp-sb-set tmp-pspace)
  720.       (labels ((seg-match (d-ctxt d-ofst r-ofsts ctxts ofsts)
  721.              (if (null ctxts) ()
  722.            (progn 
  723.              (mp-assign d-ctxt (car r-ofsts) 
  724.                   (mp-match d-ctxt d-ofst (car ctxts) (car ofsts)))
  725.              (seg-match d-ctxt d-ofst (cdr r-ofsts)
  726.                 (cdr ctxts) (cdr ofsts))))))
  727.     (mapcar (lambda (c o r) 
  728.           (seg-match c o r (contexts from) (offsets from)))
  729.         (contexts dest) (offsets dest) (offsets result))
  730.     (mp-ps-set tmp-pspace)
  731.     (mp-sb-set GC-TOP)
  732.     result)))
  733.  
  734. ; Move, several levels of move so that get and choose etc can make use
  735. ; of the appropriate bits. 
  736.  
  737.   (defun ll-move (data map initial)
  738.     ;; low-level move operation, 
  739.     (mapcar
  740.      (lambda (m-ctxt m-ofsts i-ofst)
  741.        (mapcar (lambda (d-ctxt d-ofst m-ofst)
  742.          (mp-move d-ctxt d-ofst m-ctxt m-ofst i-ofst))
  743.            (contexts data) (offsets data) m-ofsts))
  744.      (contexts map) (offsets map) (offsets initial))
  745.     (offsets initial))
  746.  
  747. ; The real meat of the operation, exceptionally nasty as this is what
  748. ; handles the nxm combinations between two virtual sets of
  749. ; communicating processors
  750.  
  751.   (defun l-move (data map p-with default)
  752.     (labels ((recurse (l-ofst cdrl-ofst)
  753.            (if (not (mp-if The-Context cdrl-ofst)) ()
  754.          (mp-assign The-Context l-ofst
  755.                 (p-with (mp-car The-Context l-ofst)
  756.                     (recurse cdrl-ofst 
  757.                          (mp-cdr The-Context cdrl-ofst)))))
  758.            (mp-else The-Context)    
  759.            (mp-assign The-Context l-ofst (mp-car The-Context l-ofst))
  760.            (mp-fi The-Context)
  761.            l-ofst))
  762.       (let ((result (make-field (paralation map)
  763.                 (mapcar mp-make-plural (contexts map))))
  764.          (tmp-pspace (mp-ps-ref)))
  765.     (mp-sb-set tmp-pspace)
  766.     (mapcar (lambda (ctxt ofst)
  767.           (mp-ps-set tmp-pspace)
  768.           (Set-The-Context ctxt)
  769.           (mp-if ctxt ofst)
  770.           (recurse ofst (mp-cdr The-Context ofst))
  771.           (mp-else ctxt)
  772.           (mp-assign ctxt ofst (mp-bang ctxt default))
  773.           (mp-fi ctxt)
  774.           ofst)
  775.         (contexts map) (ll-move data map result))
  776.     (mp-ps-set tmp-pspace)
  777.     result)))
  778.       
  779.   (defmacro move (data map with default)
  780.     `(l-move ,data ,map ,(rewire with) ,default))
  781.  
  782. ; Shaped paralations. 
  783. ; ====== ===========
  784.  
  785. ;    A shaped paralation has a predefined set of mappings which
  786. ; specify the neighbours of each element, get can be thought of as
  787. ; "each element takes it's value from the element in the given
  788. ; direction", the mappings are held in a vector in the shape slot of
  789. ; the paralation, and are extracted by the given token, e.g. N = 0.
  790. ;    We need to extend this to support shapes which do not use
  791. ; mappings, for examle rectangles making use of the nearest neighbour
  792. ; communication network of the underlying architecture. To do this we
  793. ; simply place the functions which do the move and apply this to the
  794. ; field. 
  795.  
  796.   (defun get (direction f default)
  797.     (let* ((map (vector-ref (shape f) direction))
  798.       (result (if (not (mappingp map)) (elwise (f) f)
  799.             (make-field (paralation f) (mapcar mp-make-plural
  800.                                (contexts f)))))
  801.       (tmp-pspace (mp-ps-ref)))
  802.       (mapcar (lambda (c o)
  803.         (mp-sb-set tmp-pspace)
  804.         (mp-if c o) (mp-assign c o (mp-car c o))
  805.         (mp-else c) (mp-assign c o (mp-bang c default))
  806.         (mp-fi c)
  807.         (mp-ps-set tmp-pspace) 
  808.         o)
  809.           (contexts f) (if (mappingp map) (ll-move f map result) (map result)))
  810.       (mp-sb-set GC-TOP)
  811.       result))
  812.  
  813.   (defun enum-ll (bool-f)
  814.     (let ((result (elwise (bool-f) (if bool-f 1 0)))
  815.       (tmp-pspace (mp-ps-ref)))
  816.       (labels ((recurse (c-s o-s s)
  817.          (mp-assign (car c-s) (car o-s) 
  818.                 (mp-bin-op (car c-s) 
  819.                        (mp-scan-op (car c-s) 
  820.                            (car o-s)     610)
  821.                        (mp-bang (car c-s) s)     610))
  822.          (if (null (cdr c-s)) ()
  823.            (recurse (cdr c-s) (cdr o-s)
  824.                 (mp-ref (car c-s) (car o-s) (- MP-Config 1))))))
  825.       (mp-sb-set tmp-pspace)
  826.       (recurse (contexts result) (offsets result) 0)
  827.       (mp-ps-set tmp-pspace)
  828.       (mp-sb-set GC-TOP)
  829.       result)))
  830.         
  831.   (defun enum (bool-f)
  832.     (elwise (bool-f (new (enum-ll bool-f))) (if bool-f (- new 1) ())))
  833.  
  834.   (defun choose (bool-f)
  835.     (let ((tmp (enum-ll bool-f)))
  836.       (match (make-paralation (field-ref tmp (- (field-length bool-f) 1)))
  837.          (elwise (tmp bool-f) (if bool-f (- tmp 1) ())))))
  838.  
  839.   (defun count (bool-f)
  840.     (field-ref (enum-ll bool-f) (- (field-length bool-f) 1)))
  841.  
  842.   (defun position (f o)
  843.     (let* ((tmp (elwise (f (i (index f))) (if (eq f o) i ())))
  844.        (tmp-pspace (mp-ps-ref))
  845.        (t-o (progn (mp-sb-set tmp-pspace) (mp-bang MP-Context 32768))))
  846.       (labels ((recurse (c-s o-s last)
  847.          (cond
  848.           ((null c-s) ())
  849.           ((not (mp-if (car c-s) (car o-s)))
  850.            (progn (mp-fi (car c-s)) 
  851.               (recurse (cdr c-s) (cdr o-s) (- last MP-Config))))
  852.           (t (progn
  853.                (mp-assign (car c-s) t-o (car o-s))
  854.                (mp-fi (car c-s))
  855.                (mp-ref (car c-s) (mp-scan-op (car c-s) t-o     661)
  856.                    (if (>= last MP-Config) (- MP-Config 1)
  857.                  (- last 1))))))))
  858.         (let ((result (recurse (contexts f) (offsets tmp) (field-length f))))
  859.       (mp-sb-set GC-TOP)
  860.       (mp-ps-set tmp-pspace)
  861.       result))))
  862.   
  863. (export depfun elwise match move make-paralation field-ref contexts offsets
  864.         index shape make-field Set-The-Context The-Context GC-TOP position
  865.     l-move choose enum count get fieldp field-length paralation
  866.     allocate-xec allocate-paralation index-internal rewire
  867.     shape-internal attributes paralation-internal
  868.     MP-Config MP-X-Config MP-Y-Config)
  869.  
  870.  
  871. )
  872.  
  873.